package com.example.traning.spring.ioc.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 定义切面（aspect），即通知(advice)方法所在的类，一个 aspect 类中可以有多个通知方法
 * @author lei yu
 * @since 2025/04/23
 */
@Component
@Aspect
public class LogUtil {

    /**
     * 定义切入点（pointCut），joinPoint的集合，为要添加advice(通知)的方法划定范围 <p/>
     * 有9种切入点表达式，execute,within,this,target,args,@target,@within,@annotation,@args
     */
    @Pointcut("execution(* com.example.traning.spring.ioc.aop.service..*.*(..))")
    public void pointcut() {
    }

//    /**
//     * 前置通知、前置增强(Before)
//     */
//    @Before("pointcut()")
//    public void before() {
//        System.out.println(" 方法前 " );
//    }
//    /**
//     * 返回通知(AfterReturning)
//     */
//    @AfterReturning("pointcut()")
//    public void afterReturning() {
//        System.out.println("方法返回");
//    }
//    /**
//     * 后置通知(Before)
//     */
//    @After("pointcut()")
//    public void after() {
//        System.out.println("方法后");
//    }
//    /**
//     * 异常通知(AfterThrowing)
//     */
//    @AfterThrowing("pointcut()")
//    public void afterThrowing() {
//        System.out.println("方法异常");
//    }

    /**
     * 环绕通知
     * @param joinPoint joinPoint 连接点（已存在的业务方法），joinPoint方法所在的对象称为目标对象（target）
     * @return 方法返回
     * @throws Throwable 异常
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        System.out.println("环绕通知，获取参数 " + Arrays.toString(args));
        // 执行原有方法
        Object ret = joinPoint.proceed(args);
        System.out.println("环绕通知，返回参数" + ret);
        return ret;
    }


}
